package com.iwop.moto.utils.UnionPay;

import com.alibaba.fastjson.JSON;
import com.iwop.moto.comm.Comm;
import com.iwop.moto.model.UnionPayBackInfo;
import com.iwop.moto.utils.http.HttpUtils;
import com.iwop.moto.utils.stringUtil.DateFormatter;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.codec.binary.Base64;

import java.beans.PropertyDescriptor;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.*;

public class UnionPayUtil {

    public static String SHA1WithRSA = "SHA1WithRSA";
    public static String RSA = "RSA";
    public static String pem = "pem";
    public static String UTF_8 = "UTF-8";
    public static String RSA_ECB_PKCS1Padding = "RSA/ECB/PKCS1Padding";


    /**
     * @功能: 将请求对象参数进行RSA加密签名
     * @日期: liuwb by 2016-11-21 14:22:53 create
     * @参数: params 参数集对象
     */
    public static String genSign(Map<String, String> params) throws Exception {
        PrivateKey mobomPriKey = CryptoUtil.getRSAPrivateKeyByFileSuffix(Comm.UNION_RSA_PRIVATE_PKCS8_MOBOM, pem, null, RSA);
        StringBuffer content = new StringBuffer();
        String charset = UTF_8;
        // 按照key做首字母升序排列
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys, String.CASE_INSENSITIVE_ORDER);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            if ("sign".equals(key)) {
                continue;
            }
            String value = params.get(key);
            if (isnull(value)){
                continue;
            }
            content.append((i == 0 ? "" : "&") + key + "=" + value);
        }
        String signSrc = content.toString();
        if (signSrc.startsWith("&")){
            signSrc = signSrc.replaceFirst("&", "");
        }
        byte[] plainBytes = signSrc.getBytes(charset);
        byte[] base64SingDataBytes = Base64.encodeBase64(CryptoUtil.digitalSign(plainBytes, mobomPriKey, SHA1WithRSA));
        return new String(base64SingDataBytes, charset);
    }

    public static boolean verifySign(String params,String sign) throws Exception{
        PublicKey msPubKey = CryptoUtil.getRSAPublicKeyByFileSuffix(Comm.UNION_RSA_PUBLIC_MS, pem, RSA);
        byte[] signBytes = Base64.decodeBase64(sign.getBytes(UTF_8));
        boolean verifySign = CryptoUtil.verifyDigitalSign(params.getBytes(UTF_8), signBytes, msPubKey, SHA1WithRSA);
        return verifySign;
    }

    public static String beanToUrlParams(Map<String, String> params) throws Exception {
        StringBuffer content = new StringBuffer();
        String strcontent = new String();
        // 按照key做首字母升序排列
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys, String.CASE_INSENSITIVE_ORDER);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            if ("sign".equals(key)) {
                continue;
            }
            String value = params.get(key);
            if (isnull(value)){
                continue;
            }
            content.append((i == 0 ? "" : "&") + key + "=" + value);
        }
        strcontent= content.toString();
        if (strcontent.startsWith("&")){
            strcontent = strcontent.replaceFirst("&", "");
        }
        return strcontent;
    }



    /**
     * @功能: 参数公钥加密
     * @param encryptStr
     */
    public static String RsaPublicKeyEncrypt(String encryptStr) throws Exception {
        PublicKey msPubKey = CryptoUtil.getRSAPublicKeyByFileSuffix(Comm.UNION_RSA_PUBLIC_MS, pem, RSA);
        String charset = UTF_8;
        byte[] base64EncyrptKeyBytes = Base64.encodeBase64(CryptoUtil.RSAEncrypt(
                encryptStr.getBytes(),msPubKey, 2048, 11, RSA_ECB_PKCS1Padding));
        return new String(base64EncyrptKeyBytes, charset);
    }

    public static boolean isnull(String str){
        return null == str || str.equalsIgnoreCase("null") || str.trim().equals("");
    }

    /**
     * 生成指定长度的随机字符串
     * @param length 指定字符串长度
     * @return
     */
    public static String generateLenString(int length) {
        char[] cResult = new char[length];
        int[] flag = { 0, 0, 0 }; // A-Z, a-z, 0-9
        int i = 0;
        while (flag[0] == 0 || flag[1] == 0 || flag[2] == 0 || i < length) {
            i = i % length;
            int f = (int) (Math.random() * 3 % 3);
            if (f == 0)
                cResult[i] = (char) ('A' + Math.random() * 26);
            else if (f == 1)
                cResult[i] = (char) ('a' + Math.random() * 26);
            else
                cResult[i] = (char) ('0' + Math.random() * 10);
            flag[f] = 1;
            i++;
        }
        return new String(cResult);
    }

    public static String getUnionPayInfo(String orderId,String oriNoOrder,String dt_order) throws Exception {
        Map map=new HashMap<>();
        map.put("no_order",orderId);
        map.put("oid_partner",Comm.UnpayPartner);
        map.put("ori_no_order",oriNoOrder);
        map.put("dt_order", dt_order);
        map.put("sign",genSign(map));
        String s = HttpUtils.executePost(Comm.UnpayHttpUrl + "/queryServlet", map);
        UnionPayBackInfo unionPayBackInfo = JSON.parseObject(s, UnionPayBackInfo.class);
        Map<String, String> param = beanToMap(unionPayBackInfo);
        HttpUtils.executePost(Comm.HTTP_URL+"/api/union/pay/callback",param);
        return null;
    }

    public static Map<String, String> beanToMap(Object obj) {
        Map<String, String> params = new HashMap<String, String>();
        try {
            PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
            PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(obj);
            for (int i = 0; i < descriptors.length; i++) {
                String name = descriptors[i].getName();
                if (!"class".equals(name)) {
                    params.put(name, propertyUtilsBean.getNestedProperty(obj, name)+"");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return params;
    }
}
